package cn.zwx.business.order.service.impl;

import cn.zwx.base.constant.ResponseMsg;
import cn.zwx.base.enums.RetCode;
import cn.zwx.base.exception.BizException;
import cn.zwx.base.util.Sequence;
import cn.zwx.business.order.mapper.OrderMapper;
import cn.zwx.business.order.service.OrderService;
import cn.zwx.order.clients.GoodsClient;
import cn.zwx.order.model.OrderInfo;
import cn.zwx.order.req.CreateOrderReq;
import cn.zwx.order.req.DeductionRepertoryReq;
import cn.zwx.order.req.QueryGoodsInfoReq;
import cn.zwx.order.resp.DeductionRepertoryResp;
import cn.zwx.order.resp.QueryGoodsInfoResp;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

/**
 * @description:
 * @projectName:rocket-mq-example
 * @see:cn.zwx.business.order.service.impl
 * @author:zhangwenxue
 * @createTime:2020/10/15 12:46
 * @version:1.0
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger =  LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private GoodsClient goodsClient;

    /**
     * @description 创建订单
     * @author zhangwenxue
     * @createTime 2020/10/15 13:09
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int createOrder(CreateOrderReq req) {
        //1.查询商品信息
        QueryGoodsInfoResp goodsInfo = this.getGoodsInfo(req);
        if (Math.subtractExact(goodsInfo.getGoodsNum(),req.getGoodsNum())<0){
            throw new BizException(RetCode.FAIL,"库存不足!!");
        }
        //2.创建订单
        this.builderOrderInfo(req);
        //这里面可以去消费此消息 当本地事务或者某人一个环节返回消费失败
        //则整个事务会处于回滚状态 half消息机制 实际只有全部返回commint
        //其他端才会收到可见的消息,会去执行相关代码.
        //TODO 模拟本地事务异常
        if (req.getGoodsAmount()%3==0){
            //正常情况
            return 0;
        }else if (req.getGoodsAmount()%3==1){
            //回滚状态
            throw new BizException(RetCode.FAIL,"模拟插入失败异常!!!");
        }else {
            //回查情况
            return 2;
        }

    }

    public static void main(String[] args) {
        System.out.println(1001%3);
    }
    /**
     * @description 创建订单
     * @return void
     * @author zhangwenxue
     * @createTime 2020/10/15 13:27
     **/
    private void builderOrderInfo(CreateOrderReq req) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderId(Sequence.generateBillId());
        orderInfo.setDelFlag(1);
        orderInfo.setGoodsAmount(req.getGoodsAmount());
        orderInfo.setGoodsNum(req.getGoodsNum());
        orderInfo.setGoodsId(req.getGoodsId());
        orderInfo.setGoodsName(req.getGoodsName());
        orderInfo.setOrderState(1);
        orderInfo.setPayerId(req.getPayerId());
        orderInfo.setPayerName(req.getPayerName());
        orderInfo.setTotalPayAmount(req.getTotalPayAmount());
        orderInfo.setTotalOrderAmount(new BigDecimal(req.getGoodsAmount()).multiply(new BigDecimal(req.getGoodsAmount())).longValue());
        orderInfo.setCreateTime(new Date());
        orderInfo.setUpdateTime(new Date());
        int i = orderMapper.insertSelective(orderInfo);
        if (i!=1){
            throw new BizException(RetCode.FAIL,"构建订单信息失败");
        }
    }

    /**
     * @description 扣减库存
     * @return void
     * @author zhangwenxue
     * @createTime 2020/10/15 13:20
     **/
    private void deductionRepertory(CreateOrderReq req, QueryGoodsInfoResp goodsInfo) {
        DeductionRepertoryReq repertoryReq = new DeductionRepertoryReq();
        repertoryReq.setGoodsId(goodsInfo.getGoodsId());
        repertoryReq.setGoodsNum(req.getGoodsNum());
        ResponseMsg<DeductionRepertoryResp> responseMsg = goodsClient.deductionRepertory(repertoryReq);
        if (responseMsg.isFail()){
            logger.info("扣减库存事变:请求参数{},原因:{}", JSON.toJSONString(repertoryReq),responseMsg.getDesc());
            throw new BizException(responseMsg.getCode(),responseMsg.getDesc());
        }
    }

    /**
     * @description 查询商品信息
     * @return cn.zwx.goods.resp.QueryGoodsInfoResp
     * @author zhangwenxue
     * @createTime 2020/10/15 13:17
     **/
    private QueryGoodsInfoResp getGoodsInfo(CreateOrderReq req) {
        QueryGoodsInfoReq goodsInfoReq = new QueryGoodsInfoReq();
        goodsInfoReq.setGoodsId(req.getGoodsId());
        ResponseMsg<QueryGoodsInfoResp> responseMsg = goodsClient.queryGoodsInfo(goodsInfoReq);
        if (responseMsg.isFail()){
            logger.info("查询商品信息失败:请求参数{},原因:{}", JSON.toJSONString(goodsInfoReq),responseMsg.getDesc());
            throw new BizException(responseMsg.getCode(),responseMsg.getDesc());
        }
        QueryGoodsInfoResp goodsInfo = responseMsg.getData();
        if (Objects.isNull(goodsInfo)){
            logger.info("查询商品信息失败:请求参数{},原因:{}", JSON.toJSONString(goodsInfoReq),"未查询到商品信息");
            throw new BizException(RetCode.FAIL,"未查询到商品信息");
        }

        return goodsInfo;
    }
}
